package com.study.springbootsecurity.service.impl;

import com.study.springbootsecurity.config.properties.JwtConfigProperties;
import com.study.springbootsecurity.constants.JwtTokenConstants;
import com.study.springbootsecurity.entity.SysUser;
import com.study.springbootsecurity.entity.business.RefreshResponse;
import com.study.springbootsecurity.exception.BusinessException;
import com.study.springbootsecurity.util.*;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO token令牌业务类
 * @author: Huangjianyun
 * @date: 2025-06-09 8:03
 */
@Service
@Slf4j
public class TokenService {
    // 这种方式属于构造器注入
    private final RedisCache redisCache;
    private final SysUserServiceImpl userService;
    public TokenService(RedisCache redisCache,SysUserServiceImpl userService) {
        this.redisCache = redisCache;
        this.userService = userService;
    }



    // 刷新令牌设置秒数
    public void saveRefreshToken(String refreshKey, String refreshToken, Integer refreshTime) {
        redisCache.set(refreshKey,refreshToken, refreshTime, TimeUnit.SECONDS);
    }

    public boolean isRefreshTokenValid(String refreshKey) {
        return redisCache.hasMapKey(refreshKey);
    }

    public void deleteRefreshToken(String refreshKey) {
        redisCache.deleteObject(refreshKey);
    }

    public void deleteUserInfo(String userKey) {
        redisCache.deleteObject(userKey);
    }

//    public void addToBlacklist(String accessToken, long expirationMs) {
//        // 过期访问token添加黑名单 key: blackList:accessToken value:invalid 表示token已经过期
//        redisCache.set(JwtTokenConstants.BLOCK_LIST_KEY+":"+accessToken,JwtTokenConstants.INVALID_TOKEN,expirationMs,TimeUnit.MILLISECONDS);
//    }
//
//    public boolean isInBlacklist(String accessToken) {
//        return redisCache.hasKey(JwtTokenConstants.BLOCK_LIST_KEY + accessToken);
//    }

    public RefreshResponse refreshToken(HttpServletRequest servletRequest, HttpServletResponse servletResponse, String refreshToken, JwtConfigProperties jwtConfigProperties) {
        // 校验传递刷新令牌参数和redis存储刷新令牌是否一致
        if (StringUtils.isBlank(refreshToken)) {
            //ResponseUtil.outJson(servletResponse,Result.fail(403,"refresh token is blank"));
            throw new BusinessException(403,"refresh token is blank");
        }
        String deviceFingerprint = DeviceFinerUtil.buildDeviceFingerprint(servletRequest);
        String username = TokenUtil.getUsernameFromToken(refreshToken,jwtConfigProperties);
        String refreshKey = "refresh"+":"+username+":"+deviceFingerprint;
        // boolean isExitsTokenValid = redisCache.hasKey(refreshKey);
        // boolean isRefreshTokenValid = refreshToken.equals(redisCache.getCacheObject(refreshKey));
        // 校验redis不存在刷新令牌
        // 加了这边过滤器执行多次 始终cookie添加失败
        if (!redisCache.hasKey(refreshKey)) {
            // 无法调用ResponseUtil.outJson，返回前端 response已提交，无法执行过滤器的filterchain.filter()方法
            //ResponseUtil.outJson(servletResponse,Result.fail(403,"Invalid refresh token"));
            throw new BusinessException(403,"Invalid refresh token");
        }

        // 解析刷新令牌并获取user数据,获取user数据做判断及判断解决措施
        String userKey = "user:info"+":"+username+":"+deviceFingerprint;
        SysUser user = redisCache.getCacheObject(userKey);
        if (ObjectUtils.isEmpty(user)) {
            // redis用户信息查询不到,查询数据库用户数据，重置redis用户信息
            user = userService.getByUsername(username);
            if (ObjectUtils.isEmpty(user)) {
                log.error("刷新令牌，redis用户信息查询不到,user:{}",user);
//                ResponseUtil.outJson(servletResponse, Result.fail(403, "User not found"));
//                return new RefreshResponse();
                throw new BusinessException(403,"refresh token User not found");

            }
            redisCache.set(userKey,user,jwtConfigProperties.getRefreshExpiration(), TimeUnit.MILLISECONDS);
        }
        // 创建refreshToken和生成访问令牌
        String newAccessToken = TokenUtil.createToken(user, jwtConfigProperties);
        String newRefreshToken = TokenUtil.createRefreshToken(username, jwtConfigProperties,deviceFingerprint);
        // 删除旧refreshToken后更新新的刷新令牌
        deleteRefreshToken(refreshKey);
        saveRefreshToken(refreshKey,newRefreshToken,jwtConfigProperties.getRefreshExpiration());

        //封装
        RefreshResponse refreshResponse = new RefreshResponse();
        refreshResponse.setAccessToken(newAccessToken);
        refreshResponse.setRefreshToken(newRefreshToken);

        return refreshResponse;
    }


}
